#coding:utf-8
import os.path
import random
import string
import tkinter.messagebox # 自带的图形化，不需要安装
import tkinter.filedialog
from pystrich.ean13 import EAN13Encoder
import qrcode
root=tkinter.Tk() # 建立根窗口
randstr=[] # 存储所有的防伪码
number=string.digits # '0123456789'
letter=string.ascii_letters+string.digits # letter包含大小写字母+0到9的数字串
def mkdir(path):# 用于创建文件夹的函数
    isexists=os.path.exists(path) #判断指定路径下的文件夹是否存在
    if not isexists: # 表示文件夹不存在
        os.mkdir(path) # 创建文件夹

def openfile(filename): # 读取文件中的数据
    with open(filename,'r') as file:
        content=file.read() # 结果是字符串类型
    return content

#
def inputbox(showstr,showorder,length): # 每个功能都需要用到输入 ，所以提取出一个函数
    '''
    输入并对数据进行验证
    :param showstr: input函数的 提示文本  请输入xxx
    :param showorder: 对数据验证的三种方式1,2,3
    :param length:限制数字的位数
    :return:
    '''
    instr=input(showstr) # 提示文本
    if instr: # 利用到了对象的布尔值 ，非空字符串的布尔值为True
        if showorder==1: # 纯数字串，不限制位数
            if instr.isdigit():
                if instr=='0':
                    print('输入的为0,请重新输入!')
                    return '0' # 如果在调用处使用eval()转换时, 0，没法转
                else: # '0'加上引号的目的是为了函数的返回值类型相同
                    return instr # 字符串，
            else:
                print('输入非法，请重新输入!')
                return '0'

        elif showorder==2: # 纯字母
            if instr.isalpha():
                if len(instr)!=length:
                    print(f'必须输入{length}个字母,请重新输入')
                    return '0'
                else:
                    return instr
            else:
                print('输入非法,请重新输入')
                return '0'
        elif showorder==3: # 纯数字串，限制位置
            if instr.isdigit():
                if len(instr)!=length:
                    print(f'必须输入{length}个数字，请重新输入')
                    return '0'
                else:
                    return instr
            else:
                print('输入非法，请重新输入!')
                return '0'
    else:
        print('输入为空，请重新输入')
        return '0'

def wfile(sstr,sfile,typeis,smgs,datapath):
    '''
    将防伪码写到磁盘文件
    :param sstr:  待保存的防伪码列表
    :param sfile: 保存防伪码的文件名
    :param typeis: 提示 是否显示输出 '' 表示输出 ，no表示不显示输出
    :param smgs: 提示框中的提示内容
    :param datapath: 保存防伪码的路径
    :return:
    '''
    # 创建存储防伪码的文件夹
    mkdir(datapath) # 如果文件夹不存在就创建 ，调用自定义的函数
    # 保存防伪码的路径+文件名
    datafile=datapath+'/'+sfile
    # 文件读写，覆盖写
    file=open(datafile,'w')
    wrlst=sstr # 将参数防伪码的列表赋值给wrlst  （这句代码有点累赘）
    pdata='' # 在控制台输出的内容 p-->print
    for i in range(len(wrlst)): # 遍历列表,i代表的是列表中元素的索引
        wdata=wrlst[i].replace('[','').replace(']','') #w-->write
        file.write(wdata)
        pdata+=wdata # 把所有的防伪码都拼成一个字符串
    file.close() # 可以改为with语句
    print(pdata)
    if typeis!='no': # 说明使用弹窗
        tkinter.messagebox.showinfo('提示',smgs+str(len(wrlst))+'\n防伪码文件的存放位置:'+datafile)
        root.withdraw() # 关闭辅助窗口


def menu():
    print('''
******************************************************
         企业编码生成系统
******************************************************
 1.生成6位数字防伪编码(213563型)
 2.生成9位系列产品数字防伪编码(879-335439型)
 3.生成25位混合产品序列号(B2R12-N7TE8-9IET2-FE35O-DW2K4型)
 4.生成含数据分析功能的防伪编码(5A61M0583D2)
 5.智能批量生成带数据分析功能的防伪码
 6.后续补加生成防伪码(5A61M0583D2)
 7.EAN-13条形码批量生成
 8.二维码批量输出
 9.企业粉丝防伪码抽奖
 0.退出系统

    ''')

def main():
    while True:
        menu()
        choice=eval(input('请输入您要操作的菜单选项:'))
        if choice==1:
            scode1(choice) # choice函数的实参
        elif choice==2:
            scode2(choice)
        elif choice==3:
            scode3(choice)
        elif choice==4:
            scode4(choice)
        elif choice==5:
            scode5(choice)
        elif choice==6:
            scode6(choice)
        elif choice==7:
            scode7(choice)
        elif choice==8:
            scode8(choice)
        elif choice==9:
            scode9(choice)
        elif choice==0:
            print('正在退出系统!!')
            break # 退出循环 while True
        else:
            print('对不起，功能菜单选择有误!!!')
def scode1(schoice):
    # 调用inputbox函数
    incount=inputbox('请输入要产生的防伪码的数量:',1,0)
    while eval(incount)==0:
        incount = inputbox('请输入要产生的防伪码的数量:', 1, 0)
    randstr.clear() # 清空全局变量（列表类型）中的内容
    for j in range(eval(incount)): # incount产生的个数
        ranfir='' # 存储单个数字
        for i in range(6): # choice()是random中一个函数
            ranfir+=random.choice(number) # 随机从字符串中取出一个数字
        ranfir+='\n' # 内层循环执行完一次之后，一个防伪码就产生
        randstr.append(ranfir) # 将一个防伪码放到列表中存储
    # 外层循环控制的是产生的防伪码的个数
    # 将产生的防伪码写入文件
    wfile(randstr,'scode'+str(schoice)+'.txt','','已生成6位的防伪码共计:','codepath')


def scode2(schoice):
    # 验证产品起始号  纯数字，3位数字
    ordstart=inputbox('请输入系列产品的数字起始号:',3,3)
    while eval(ordstart)==0:
        ordstart = inputbox('请输入系列产品的数字起始号:', 3, 3)
    # 验证产品系列的数量
    ordcount=inputbox('请输入系列产品的数量:',1,0)
    while eval(ordcount)==0:
        ordcount = inputbox('请输入系列产品的数量:', 1, 0)

    # 每个系列产品的防伪码数量
    incount=inputbox('请输入每个系列产品防伪码的数量:',1,0)
    while eval(incount)==0:
        incount = inputbox('请输入每个系列产品防伪码的数量:', 1, 0)
    randstr.clear() # 清空存储防伪码列表中的元素
    for m in range(eval(ordcount)): # 有多少个产品，m的值从0开始
        for j in range(eval(incount)): # 每个产品 ，产生多少个？
            randfir='' # 每个防伪中由6个数字组成
            for i in range(6):
                randfir+=random.choice(number)
            randstr.append(str(eval(ordstart)+m)+randfir+'\n')
    # 调用输出
    wfile(randstr,'scode'+str(schoice)+'.txt','','已生成9位的系列产品防伪码共计:','codepath')

#18602218136  atxunda.com

def scode3(schoice):
    # 输入需要产生的防伪码的数量
    incount=inputbox('请输入要产生的25位混合产品序列号的数量:',1,0)
    while eval(incount)==0:
        incount = inputbox('请输入要产生的25位混合产品序列号的数量:', 1, 0)
    randstr.clear() # 清空存储防伪码的列表
    for j in range(eval(incount)): # 按照输入数量去生成防伪码
        strone='' # 保存一个防伪码
        for i in range(25): # 防伪码的个数是25位
            strone+=random.choice(letter) # 每次随机取一个进行拼接
        # 每5位开始连接一个减号  字符串的切片操作
        strtwo=strone[0:5]+'-'+strone[5:10]+'-'+strone[10:15]+'-'+strone[15:20]+'-'+strone[20:]+'\n'
        randstr.append(strtwo)
    # 调用写入的函数
    wfile(randstr,'scode'+str(schoice)+'.txt','','已生成25位的防伪码共:','codepath')

def scode4(schoice):
    intype=inputbox('请输入数据分析的编号(3位字符):',2,3)
    # intype不是字母或长度不等于3时重新输入
    while not  intype.isalpha() or len(intype)!=3:
        intype = inputbox('请输入数据分析的编号(3位字符):', 2, 3)
    # 验证输入的个数
    incount=inputbox('请输入要生成的带有数据分析功能的防伪码的数量:',1,0)
    while eval(incount)==0:
        incount = inputbox('请输入要生成的带有数据分析功能的防伪码的数量:', 1, 0)
    # 生成防伪码 ,调用一个自定义的函数
    ffcode(incount,intype,'',schoice)

def ffcode(scount,typestr,ismessage,schoice):
    '''
    :param scount: 产生的防伪码的数量
    :param typestr: 带有数据分析的编号 3位的字母
    :param ismessage:  ‘’表示使用提示弹框
    :param schoice:  用户的选择
    :return:
    '''
    randstr.clear() # 将存储防伪码的列表进行清空
    for j in range(eval(scount)): # 根据用户的输入数量产生防伪码
        strpro=typestr[0].upper()# 区域分析码
        strtype=typestr[1].upper()# 颜色分析码
        strclass=typestr[2].upper() # 版本分析码
        # 产生数据分析码的插入位置
        randfir=random.sample(number,3) # number是0到9的数字
        randsec=sorted(randfir) # 对产生的数字进行排序
        letterone='' # 存储单个防伪码的
        for i in range(10):
            letterone+=random.choice(number) # 产生的是数字
        # 切片操作 ，拼接 数据分析码
        sim=(letterone[0:eval(randsec[0])]+strpro+
             letterone[eval(randsec[0]):eval(randsec[1])]+strtype+
             letterone[eval(randsec[1]):eval(randsec[2])]+strclass+
             letterone[eval(randsec[2]):]+'\n')
        randstr.append(sim)
    # 调用输出
    wfile(randstr,typestr+'scode'+str(schoice)+'.txt',ismessage,'生成含有数据分析功能的防伪码共:','codepath')


def scode5(schoice):
    default_dir=r'xd.mri' # 打开的文件
    file_path=tkinter.filedialog.askopenfilename(filetypes=[('Text File','*.mri')],
                                                 title='请选择智能批量处理文件',
                                                 initialdir=os.path.expanduser(default_dir))
    codelst=openfile(file_path) # codelst是字符串类型
    codelst=codelst.split('\n') # 字符串对象的方法,codelst就是列表类型
    print(codelst,type(codelst))
    for item in codelst: # 遍历列表,item是字符串类型 aba,20
        codea=item.split(',')[0] # 系列产品的编号
        codeb=item.split(',')[1] # 生成的防伪码的数量
        # 生成防伪码
        ffcode(codeb,codea,'no',schoice)


def scode6(schoice):
    default_dir='scode5.txt'
    file_path=tkinter.filedialog.askopenfilename(title='请选择已生成的防伪码的文件',
                                                 initialdir=os.path.expanduser(default_dir))
    codelst=openfile(file_path) # codelst是一个字符串类型
    codelst=codelst.split('\n')# codelst的类型列表
    codelst.remove('') # 将列表中的空字符串删除
    strset=codelst[0] # 这个字符串7344A202B4I23
    # 把strset中的字母取出来，将数字删除
    remove_digit=strset.maketrans('','',string.digits)
    rrest_letter=strset.translate(remove_digit) # rrest_letter就剩字母了

    strpro=rrest_letter[0] # 区域分析码
    strtype=rrest_letter[1] # 颜色分析码
    strclass=rrest_letter[2] # 版次分析码
    # 新产生的防伪码与文本文件中的防伪码不能相同
    card=set(codelst) # 实现了去重
    # 消息框提示原来有多少
    tkinter.messagebox.showinfo('提示','之前防伪码的数量:'+str(len(card)))
    # 关闭消息框
    root.withdraw()
    # 输入需要新产生的防伪码的数量
    incount=inputbox('请输入补充防伪码的数量:',1,0)
    while eval(incount)==0:
        incount = inputbox('请输入补充防伪码的数量:', 1, 0)
    # 循环的次数是输入的2倍去产生防伪码
    for j in range(eval(incount)*2):
        # 开始准备产生防伪码
        # 产生数据分析码的插入位置
        randfir = random.sample(number, 3)  # number是0到9的数字
        randsec = sorted(randfir)  # 对产生的数字进行排序
        addcount=len(card) # 计算原来的数量
        letterone = ''  # 存储单个防伪码的
        for i in range(10):
            letterone += random.choice(number)  # 产生的是数字
        # 切片操作 ，拼接 数据分析码
            sim = (letterone[0:eval(randsec[0])] + strpro +
               letterone[eval(randsec[0]):eval(randsec[1])] + strtype +
               letterone[eval(randsec[1]):eval(randsec[2])] + strclass +
               letterone[eval(randsec[2]):] + '\n')
        card.add(sim) # 添加到集中的作用是为了去重
        # 判断是否有重复
        if len(card)>addcount: # 说明没有重复
            randstr.append(sim) # 没有重复再往列表中添加
            addcount=len(card) #
        # 循环什么时候结束
        if len(randstr)>=eval(incount):
            print(len(randstr))
            break

    # 退出循环之后要做的事情就是调函数
    wfile(randstr,rrest_letter+'code'+str(schoice)+'.txt','','生成补充的防伪码数量:','codepath')
def scode7(schoice):
    mainid=inputbox('请输入EAN13的国家代码(3位):',3,3)
    while eval(mainid)==0:
        mainid = inputbox('请输入EAN13的国家代码(3位):', 3, 3)

    compid=inputbox('请输入企业码(4位):',3,4)
    while eval(compid)==0:
        compid = inputbox('请输入企业码(4位):', 3, 4)

    incount=inputbox('请输入要生成的条形码的个数:',1,0)
    while eval(incount)==0:
        incount = inputbox('请输入要生成的条形码的个数:', 1, 0)
    mkdir('barcode') # 检测存储条形码的文件夹是否存在，不存在就创建
    for j in range(eval(incount)):#循环创建条形码
        strone=''
        for i in range(5): # 产品码5位，采用随机数
            strone+=random.choice(number)
        barcode=mainid+compid+strone # barcode多少位了？
        # 计算最后一位的校验位
        evensum=eval(barcode[1])+eval(barcode[3])+eval(barcode[5])+eval(barcode[7])+eval(barcode[9])+eval(barcode[11])
        oddsum=eval(barcode[0])+eval(barcode[2])+eval(barcode[4])+eval(barcode[6])+eval(barcode[8])+eval(barcode[10])
        checkbit=(10-(evensum*3+oddsum)%10)%10
        barcode=barcode+str(checkbit) # 连接上校验位
        # 生成条形码
        encoder=EAN13Encoder(barcode)
        encoder.save('barcode\\'+barcode+'.png')

def scode8(schoice):
    # 请输入要生成的二维码的数量
    incount=inputbox('请输入要生成的二维码的数量:',1,0)
    while eval(incount)==0:
        incount = inputbox('请输入要生成的二维码的数量:', 1, 0)
    # 调用mkdir()函数创建文件夹
    mkdir('qrcode')
    for j in range(eval(incount)):
        strone=''
        for i in range(12): # 12表示的是循环的执行次数
            strone+=random.choice(number) # '0123456789'
        # 制作二维码
        encoder=qrcode.make(strone)
        encoder.save('qrcode\\'+strone+'.png')

def scode9(schoice):
    default_dir='lottroy.ini'
    file_path=tkinter.filedialog.askopenfilename(filetypes=[('Ini File','*.ini')],
                                                 title='请选择要打开的文件',initialdir=os.path.expanduser(default_dir))
    codelst=openfile(file_path) #codelst是字符串类型
    codelst=codelst.split('\n') # codelst 是列表类型
    codelst.remove('') # 将列表中的空字符串进行删除
    incount=inputbox('请输入要生成的中奖的数量:',1,0)
    while eval(incount)==0 or len(codelst)<eval(incount):
        incount = inputbox('请输入要生成的中奖的数量:', 1, 0)
    # 根据中奖的数量抽取出中奖的人员
    strone=random.sample(codelst,eval(incount)) # strone是一个列表
    for item in strone:
        print(f'中奖号码为:{item}')

if __name__ == '__main__':
    #path='d:/pythonpro/2024-7-22/code'
    #mkdir(path)
    #print(openfile('xd.mri'))
    main()
    # x=inputbox('请输入要生的防伪码的数量:',1,0)
    # print(x)
    # y=inputbox('请输入产品的类别:',2,3)
    # print(y)                                               #length取值范是100-999
    # z=inputbox('请输入XXx的数量：',showorder=3,length=3)
    # print(z)
    #wfile(['[123456]\n','[7894]\n','[5555]\n'],'code1.txt','','一共有多少个元素','codepath')
    # 18602218136